package com.zhuoyue.utils;

import java.io.ByteArrayOutputStream;

/**
 *
 * 透明传输的方式
 *
 *
 * 目前仅仅支持一种。
 *
 * 采用字节填充的方式填充0XFF,0XFF
 *
 *
 * @author Created by mr.liang
 */
public class PassthroughCode {


    public static byte[] SPLIT_BYTES = new byte[]{(byte) 0xFF, (byte) 0XFF};


    /**
     * 字节填充
     *
     * 为什么要选两个字节的？
     *  两个字节重复的几率可能会小很多
     *
     * 为什么要     0XFF,0XFE => 0XFF,0XFF,0XFD  然后 0XFE,0XFE => 0XFE,0XFE,0XFC
     * 为什么不直接  0XFF,0XFF => 0XFF,0XFF,0XFD  （这种明显少了一步转换）
     *
     * 因为我需要直接用0XFF,0XFF作为分割符
     *
     */
    public static byte[] encode(byte[] bytes) {

        if (bytes.length < 2) {
            return bytes;
        }

        ByteArrayOutputStream bao = new ByteArrayOutputStream(bytes.length + bytes.length/10);

        byte[] temp = new byte[2];

        for(int i=0,speedNum,unread;i<bytes.length;){
            temp[0] = bytes[i];
            temp[1] = bytes[i+1];

            if(temp[1] == (byte)0XFF){
                if(temp[0] == (byte)0XFF){

                    bao.write((byte)0XFE);
                    bao.write((byte)0XFE);
                    bao.write((byte)0XFD);

                    speedNum = 2;
                }else{
                    bao.write(temp[0]);
                    speedNum = 1;
                }
            } else if(temp[1] == (byte)0XFE){
                if(temp[0] == (byte)0XFE){

                    bao.write((byte)0XFE);
                    bao.write((byte)0XFE);
                    bao.write((byte)0XFC);

                    speedNum = 2;
                }else{
                    bao.write(temp[0]);
                    speedNum = 1;
                }
            } else{
                bao.write(temp[0]);
                bao.write(temp[1]);
                speedNum = 2;
            }

            unread = bytes.length - i -2;//表示未读
            if(unread == 0){
                if(speedNum == 1){//说明仅仅读了temp[0]
                    bao.write(temp[1]);//把下一个也读了返回
                }
                break;
            }else if(unread == 1 && speedNum == 2){
                bao.write(bytes[i+2]);//把最后一个读完返回
                break;
            }else{
                i+=speedNum;
            }
        }
        return bao.toByteArray();
    }


    /**
     * 进行字节填充解码
     *
     * 0XFE,0XFE,0XFD => 0XFF,0XFF
     * 0XFE,0XFE,0XFC => 0xFE,0XFE
     */
    public static byte[] decode(byte[] bytes){
        if(bytes.length<3)
            return bytes;

        ByteArrayOutputStream bao = new ByteArrayOutputStream(bytes.length);

        byte[] temp = new byte[3];

        for (int i = 0,speedNum,unread;i < bytes.length -2; ) {
            temp[0] = bytes[i];
            temp[1] = bytes[i+1];
            temp[2] = bytes[i+2];


            if((byte)0XFE==temp[1]){

                if((byte)0XFE==temp[0]){
                    if((byte)0XFC==temp[2]){// 0XFE 0XFE 0XFC
                        bao.write((byte)0XFE);
                        bao.write((byte)0XFE);
                        speedNum =3;
                    }else if((byte)0XFD==temp[2]){// 0XFE 0XFE 0XFD
                        bao.write((byte)0XFE);
                        bao.write((byte)0XFF);
                        speedNum =3;
                    }else if((byte)0XFE==temp[2]){// 0XFE 0XFE 0XFE
                        bao.write(temp[0]);
                        speedNum =1;
                    }else{// 0XFE 0XFE 0X...(not FC,FD,FE)
                        bao.write(temp[0]);
                        bao.write(temp[1]);
                        bao.write(temp[2]);
                        speedNum =3;
                    }
                }
                else if((byte)0XFE==temp[2]){// 0X...(not FE) 0XFE 0XFE
                    speedNum =1;
                    bao.write(temp[0]);
                }else{//0X...(not FE) 0XFE 0X...(not FE)
                    bao.write(temp[0]);
                    bao.write(temp[1]);
                    bao.write(temp[2]);
                    speedNum =3;
                }
            }
            else if((byte)0XFE==temp[2]){// 0X...(任意) 0X...(not FE) 0XFE
                bao.write(temp[0]);
                bao.write(temp[1]);
                speedNum =2;
            }else{//// 0X...(任意) 0X...(not FE) 0X...(not FE)
                bao.write(temp[0]);
                bao.write(temp[1]);
                bao.write(temp[2]);
                speedNum =3;
            }

            unread = bytes.length - i -3;//表示未读
            if(unread > 2){
                i+=speedNum;
            }
            else if(unread == 0){
                if(speedNum == 1){//说明仅仅读了temp[0]
                    bao.write(temp[1]);
                    bao.write(temp[2]);
                }else if(speedNum == 2){
                    bao.write(temp[2]);
                }
                break;
            }else if(unread == 1 && speedNum!=1){
                if(speedNum == 2){
                    bao.write(temp[2]);//
                }
                bao.write(bytes[i+3]);//speedNum == 3
                break;
            }else if(unread == 2 && speedNum==3){
                bao.write(bytes[i+3]);
                bao.write(bytes[i+4]);
                break;
            }else{
                i+=speedNum;
            }
        }

        return bao.toByteArray();
    }


}
